home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUTORC.ZIP / TUTSUBS.C < prev    next >
C/C++ Source or Header  |  1994-10-30  |  21KB  |  792 lines

  1. /* 
  2.   tutsubs.c
  3.   10/30/94
  4.   from gfx2.pas
  5.   Adapted from Denthor's gfx2.pas
  6.   Translated into C, from Denthor's VGA Trainer, by
  7.   Steve Pinault, scp@ohm.att.com
  8.   Compiled with Microsoft Visual C++ 1.5 (Microsoft C 8.0)
  9.   To compile:
  10.   First compile the subroutines in tutsubs.c with the batch file 
  11.   cltutsub.bat
  12.   Then compile any of the tutor programs with the batch file
  13.   cltut.bat
  14.   Example: C:>cltutsub
  15.            C:>cltut tut2.c
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <dos.h>
  21. #include <math.h>
  22. #include <conio.h>
  23. #include <graph.h>
  24. #include <bios.h>
  25. #include <string.h> 
  26. #include <time.h> 
  27. #include "tutheadr.h"
  28.  
  29.  
  30. //DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  31. //Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  32. void SetMCGA()
  33. {
  34.   _asm
  35.   {
  36.      mov        ax,0013h
  37.      int        10h
  38.   }
  39. }
  40.  
  41.  
  42. //DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  43. //Procedure SetText;  { This procedure returns you to text mode.  }
  44. void SetText()
  45. {
  46.   _asm
  47.   {
  48.      mov        ax,0003h
  49.      int        10h
  50.   }
  51. }
  52.  
  53.  
  54. //{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  55. //procedure WaitRetrace; assembler;
  56. /*
  57.     This waits until you are in a Verticle Retrace ... this means that all
  58.     screen manipulation you do only appears on screen in the next verticle
  59.     retrace ... this removes most of the "fuzz" that you see on the screen
  60.     when changing the pallette. It unfortunately slows down your program
  61.     by "synching" your program with your monitor card ... it does mean
  62.     that the program will run at almost the same speed on different
  63.     speeds of computers which have similar monitors. In our SilkyDemo,
  64.     we used a WaitRetrace, and it therefore runs at the same (fairly
  65.     fast) speed when Turbo is on or off. 
  66. */
  67.  
  68. void WaitRetrace()
  69. {
  70.   _asm
  71.   {
  72.     mov dx,3DAh
  73. l1:
  74.     in al,dx
  75.     and al,08h
  76.     jnz l1
  77. l2:
  78.     in al,dx
  79.     and al,08h
  80.     jz  l2
  81.   }
  82. }
  83.  
  84.  
  85. //DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  86. //Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte);
  87. void GetPal(char ColorNo, char* R, char* G, char* B)
  88. //  This reads the values of the Red, Green and Blue values of a certain
  89. //  color and returns them to you. 
  90. {
  91.    outp(0x3c7,ColorNo);
  92.    *R=inp(0x3c9);
  93.    *G=inp(0x3c9);
  94.    *B=inp(0x3c9);
  95. }
  96.  
  97.  
  98. //DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  99. //Procedure Pal(ColorNo : Byte; R,G,B : Byte);
  100. void Pal(char ColorNo, char R, char G, char B)
  101. //  This sets the Red, Green and Blue values of a certain color 
  102. {
  103.    outp(0x3c8,ColorNo);
  104.    outp(0x3c9,R);
  105.    outp(0x3c9,G);
  106.    outp(0x3c9,B);
  107. }
  108.  
  109. //////////////////////////////////////////////////////////////
  110. void SetAllPal(char far* pal)
  111.   outp(0x3c8,0x0); // Set to first color
  112.   _asm
  113.   {
  114.     mov  cx,768
  115.     lds  si,pal   // loads pal into ds:si
  116.     mov  dx,0x3c9  
  117.     rep  outsb    // sends out the string pointed to by ds:si
  118.   }
  119. }
  120.  
  121. //DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  122. //Procedure PutPixel (X,Y : Integer; Col : Byte);
  123. //  This puts a pixel on the screen by writing directly to memory. 
  124. void PutPixel(int X, int Y, char Color, int Where)
  125. {
  126.   unsigned char far* VGAScreenPtr;
  127.   unsigned int offset;
  128.   offset=(unsigned)X + (unsigned)(Y<<8) + (unsigned)(Y<<6);
  129.   VGAScreenPtr=MK_FP(Where,offset);
  130.   *VGAScreenPtr=Color;
  131. }
  132.  
  133. ////////////////////////// line //////////////////////////////////
  134. //  Procedure line(a,b,c,d,col:integer);
  135. //  This draws a line from a,b to c,d of color col. }
  136. //  This routine is adapted from Programmer's Guide to the EGA and VGA Cards,
  137. //  by Ferraro. It's Bresenham's algorithm. I used it instead of translating
  138. //  the one in the trainer because I already had it and it worked.
  139.  
  140. void Line(int x1, int y1, int x2, int y2, unsigned char Color)
  141.  
  142. {
  143.   int dx,dy,incr1,incr2,d,x,y,xend,yend,yinc,xinc;
  144.  
  145.   dx=abs(x2-x1);
  146.   dy=abs(y2-y1);
  147.  
  148.   if(dx>=dy) // slope < 1
  149.   {
  150.     if(x1>x2)
  151.     {
  152.       x=x2; y=y2; xend=x1;
  153.       if(dy==0) yinc=0;
  154.       else { if(y2>y1) yinc=-1; else yinc=1;}
  155.     }
  156.     else
  157.     {
  158.       x=x1; y=y1; xend=x2;
  159.       if(dy==0) yinc=0;
  160.       else { if(y2>y1) yinc=1; else yinc=-1;}
  161.     }
  162.     incr1=2*dy; d=incr1-dx; incr2=2*(dy-dx);
  163.     PutPixel(x,y,Color,VGA);
  164.     while(x<xend)
  165.     {
  166.       x++;
  167.       if(d<0) d+=incr1;
  168.       else { y+=yinc; d+=incr2;}
  169.       PutPixel(x,y,Color,VGA);
  170.     }
  171.   }
  172.   else
  173.   {
  174.     if(y1>y2)
  175.     { 
  176.       x=x2; y=y2; yend=y1;
  177.       if(dx==0) xinc=0;
  178.       else { if(x2>x1) xinc = -1; else xinc = 1;}
  179.     }
  180.     else
  181.     {
  182.       x=x1; y=y1; yend=y2;
  183.       if(dx==0) xinc=0;
  184.       else { if(x2>x1) xinc=1; else xinc = -1;}
  185.     }
  186.     incr1=2*dx; d=incr1-dy; incr2=2*(dx-dy);
  187.     PutPixel(x,y,Color,VGA);
  188.     while(y<yend)
  189.     {
  190.       y++;
  191.       if(d<0) d+=incr1;
  192.       else { x+=xinc; d+=incr2; }
  193.       PutPixel(x,y,Color,VGA);
  194.     }
  195.   }
  196. }
  197. //////////////////////////////////////////////////////////////////
  198.  
  199. void Line2(int x1, int y1, int x2, int y2, unsigned char Color, int where)
  200. // Same as Line (above), except takes the argument where instead of
  201. // being hard coded to write to VGA.
  202.  
  203. //////////////////////////////////////////////////////////////////
  204. {
  205.   int dx,dy,incr1,incr2,d,x,y,xend,yend,yinc,xinc;
  206.  
  207.   dx=abs(x2-x1);
  208.   dy=abs(y2-y1);
  209.  
  210.   if(dx>=dy) // slope < 1
  211.   {
  212.     if(x1>x2)
  213.     {
  214.       x=x2; y=y2; xend=x1;
  215.       if(dy==0) yinc=0;
  216.       else { if(y2>y1) yinc=-1; else yinc=1;}
  217.     }
  218.     else
  219.     {
  220.       x=x1; y=y1; xend=x2;
  221.       if(dy==0) yinc=0;
  222.       else { if(y2>y1) yinc=1; else yinc=-1;}
  223.     }
  224.     incr1=2*dy; d=incr1-dx; incr2=2*(dy-dx);
  225.     PutPixel(x,y,Color,where);
  226.     while(x<xend)
  227.     {
  228.       x++;
  229.       if(d<0) d+=incr1;
  230.       else { y+=yinc; d+=incr2;}
  231.       PutPixel(x,y,Color,where);
  232.     }
  233.   }
  234.   else
  235.   {
  236.     if(y1>y2)
  237.     { 
  238.       x=x2; y=y2; yend=y1;
  239.       if(dx==0) xinc=0;
  240.       else { if(x2>x1) xinc = -1; else xinc = 1;}
  241.     }
  242.     else
  243.     {
  244.       x=x1; y=y1; yend=y2;
  245.       if(dx==0) xinc=0;
  246.       else { if(x2>x1) xinc=1; else xinc = -1;}
  247.     }
  248.     incr1=2*dx; d=incr1-dy; incr2=2*(dx-dy);
  249.     PutPixel(x,y,Color,where);
  250.     while(y<yend)
  251.     {
  252.       y++;
  253.       if(d<0) d+=incr1;
  254.       else { x+=xinc; d+=incr2; }
  255.       PutPixel(x,y,Color,where);
  256.     }
  257.   }
  258. }
  259.  
  260.  
  261. ////////////////////////// Funny_Line //////////////////////////////////
  262.  
  263. void Funny_Line(int x1, int y1, int x2, int y2, int where)
  264.  
  265. //////////////////////////////////////////////////////////////////
  266. {
  267.   int dx,dy,incr1,incr2,d,x,y,xend,yend,yinc,xinc;
  268.   int count = 50;
  269.  
  270.   dx=abs(x2-x1);
  271.   dy=abs(y2-y1);
  272.  
  273.   if(dx>=dy) // slope < 1
  274.   {
  275.     if(x1>x2)
  276.     {
  277.       x=x2; y=y2; xend=x1;
  278.       if(dy==0) yinc=0;
  279.       else { if(y2>y1) yinc=-1; else yinc=1;}
  280.     }
  281.     else
  282.     {
  283.       x=x1; y=y1; xend=x2;
  284.       if(dy==0) yinc=0;
  285.       else { if(y2>y1) yinc=1; else yinc=-1;}
  286.     }
  287.     incr1=2*dy; d=incr1-dx; incr2=2*(dy-dx);
  288.     PutPixel(x,y,(char)count,where);
  289.     count++;
  290.     if(count==101)count=50;
  291.     while(x<xend)
  292.     {
  293.       x++;
  294.       if(d<0) d+=incr1;
  295.       else { y+=yinc; d+=incr2;}
  296.       PutPixel(x,y,(char)count,where);
  297.       count++;
  298.       if(count==101)count=50;
  299.     }
  300.   }
  301.   else
  302.   {
  303.     if(y1>y2)
  304.     { 
  305.       x=x2; y=y2; yend=y1;
  306.       if(dx==0) xinc=0;
  307.       else { if(x2>x1) xinc = -1; else xinc = 1;}
  308.     }
  309.     else
  310.     {
  311.       x=x1; y=y1; yend=y2;
  312.       if(dx==0) xinc=0;
  313.       else { if(x2>x1) xinc=1; else xinc = -1;}
  314.     }
  315.     incr1=2*dx; d=incr1-dy; incr2=2*(dx-dy);
  316.     PutPixel(x,y,(char)count,where);
  317.     count++;
  318.     if(count==101)count=50;
  319.     while(y<yend)
  320.     {
  321.       y++;
  322.       if(d<0) d+=incr1;
  323.       else { x+=xinc; d+=incr2; }
  324.       PutPixel(x,y,(char)count,where);
  325.       count++;
  326.       if(count==101)count=50;
  327.     }
  328.   }
  329. }
  330. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  331. // Procedure PalPlay;
  332. void PalPlay()
  333. {
  334. //  This procedure mucks about with our "virtual pallette", then shoves it
  335. //  to screen. 
  336. //  This is used as a "temporary color" in our pallette:
  337.     char Tmp[3];
  338.  
  339. // This copies color 200 from our virtual pallette to the Tmp variable:
  340.    _fmemmove(Tmp,Pall[200],3);
  341. // This moves the entire virtual pallette up one color:
  342.    _fmemmove(Pall[2],Pall[1],199*3);
  343. // This copies the Tmp variable to the bottom of the virtual pallette:
  344. // Don't change 0: leave this always black to not change overscan color.
  345.    _fmemmove(Pall[1],Tmp,3);
  346.    WaitRetrace();
  347.    SetAllPal((char far*)&Pall[0][0]);
  348. }
  349.  
  350. //////////////////////////////////////////////////////////////////////
  351. // More general purpose version of the above routine, used in tut7.c:
  352. // Moves all colors up one. Note fmemmove is (dest,src)
  353.  
  354. void rotatepal(char locpal[][3], int start, int end)
  355. {
  356.    char Tmp[3];
  357.    int loop1;
  358.    int number=end-start;
  359.  
  360.    _fmemmove(Tmp,locpal[end],3);
  361.    _fmemmove(locpal[start+1],locpal[start],number*3);
  362.    _fmemmove(locpal[start],Tmp,3);
  363.    WaitRetrace();
  364.    for(loop1=start;loop1<end+1;loop1++)
  365.      Pal((unsigned char)loop1,locpal[loop1][0],locpal[loop1][1],
  366.                               locpal[loop1][2]);
  367. }
  368.  
  369.  
  370. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  371. // Procedure GrabPallette;
  372. void GrabPallette()
  373. {
  374.   int loop1;
  375.   for(loop1=0;loop1<256;loop1++)
  376.   {
  377.     GetPal((unsigned char)loop1,&Pall2[loop1][0],&Pall2[loop1][1],&Pall2[loop1][2]);
  378.   }
  379. }
  380.  
  381. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  382. // Procedure Blackout;
  383. //  This procedure blackens the screen by setting the pallette values of
  384. //  all the colors to zero. 
  385. void Blackout()
  386. {
  387.   int loop1;
  388.   WaitRetrace();
  389.   for(loop1=0;loop1<256;loop1++)
  390.   {
  391.     Pal((unsigned char)loop1,0,0,0);
  392.   }
  393. }
  394.  
  395. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  396. // Procedure Fadeup;
  397. // This procedure slowly fades up the new screen }
  398. void FadeUp()
  399. {
  400.   int loop1,loop2;
  401.   char Tmp[3]; // This is temporary storage for the values of a color 
  402.  
  403.   // A color value for Red, green or blue is 0 to 63, so this loop only
  404.   // need be executed a maximum of 64 times:
  405.   for(loop1=0;loop1<64;loop1++)
  406.   {
  407.     WaitRetrace();
  408.     for(loop2=0;loop2<256;loop2++)
  409.     {
  410.       GetPal((unsigned char)loop2,&Tmp[0],&Tmp[1],&Tmp[2]);
  411.       // If the Red, Green or Blue values of color loop2 are less then they
  412.       // should be, increase them by one: 
  413.       if(Tmp[0]<Pall2[loop2][0]) Tmp[0]++;
  414.       if(Tmp[1]<Pall2[loop2][1]) Tmp[1]++;
  415.       if(Tmp[2]<Pall2[loop2][2]) Tmp[2]++;
  416.       // Set the new, altered pallette color: 
  417.       Pal((unsigned char)loop2,Tmp[0],Tmp[1],Tmp[2]);
  418.     }
  419.   }
  420. }
  421.  
  422. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  423. // Procedure FadeDown;
  424. // This procedure fades the screen out to black. }
  425. void FadeDown()
  426. {
  427.   int loop1,loop2;
  428.   char Tmp[3]; // This is temporary storage for the values of a color 
  429.  
  430.   // A color value for Red, green or blue is 0 to 63, so this loop only
  431.   // need be executed a maximum of 64 times:
  432.   for(loop1=0;loop1<64;loop1++)
  433.   {
  434.     WaitRetrace();
  435.     for(loop2=0;loop2<256;loop2++)
  436.     {
  437.       GetPal((unsigned char)loop2,&Tmp[0],&Tmp[1],&Tmp[2]);
  438.       // If the Red, Green or Blue values of color loop2 are not yet zero,
  439.       // then, decrease them by one. }
  440.       if(Tmp[0]>0) Tmp[0]--;
  441.       if(Tmp[1]>0) Tmp[1]--;
  442.       if(Tmp[2]>0) Tmp[2]--;
  443.       // Set the new, altered pallette color: 
  444.       Pal((unsigned char)loop2,Tmp[0],Tmp[1],Tmp[2]);
  445.     }
  446.   }
  447. }
  448.  
  449. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  450. // Procedure RestorePallette;
  451. // This procedure restores the origional pallette 
  452. void RestorePallette()
  453. {
  454.   int loop1;
  455.   WaitRetrace();
  456.   for(loop1=0;loop1<256;loop1++)
  457.     Pal ((unsigned char)loop1,Pall2[loop1][0],Pall2[loop1][1],Pall2[loop1][2]);
  458. }
  459.  
  460. ///////////////////////////////////////////////////////////////////////////////
  461.  
  462. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  463. // Procedure Cls (Col : Byte; Where:Word);
  464. // This clears the screen to the specified color, on the VGA or on the
  465. // virtual screen 
  466. // Argument Where will be either VGA or Vaddr: the SEG of the Screen Pointer.
  467. void Cls(char Color, int Where)
  468. {
  469.   unsigned char far* ScreenPtr;
  470.   ScreenPtr=MK_FP(Where,0x0);
  471.   _fmemset(ScreenPtr,Color,(unsigned int)64000);
  472. }
  473.  
  474. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  475. // Procedure Flip;
  476. // { This flips the virtual screen to the VGA screen. }
  477. void Flip()
  478. {
  479.   unsigned char far* ScreenPtr;
  480.   ScreenPtr=MK_FP(VGA,0x0);
  481.   _fmemmove(ScreenPtr,VirtPtr,(unsigned int)64000);
  482. }
  483.  
  484. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  485. // procedure flip(source,dest:Word);
  486. //   { This copies the entire screen at "source" to destination }
  487. void Flip2(int Source, int Dest)
  488. {
  489.   _asm
  490.   {
  491.     push    ds
  492.     mov     ax, Dest
  493.     mov     es, ax
  494.     mov     ax, Source
  495.     mov     ds, ax
  496.     xor     si, si
  497.     xor     di, di
  498.     mov     cx, 32000
  499.     rep     movsw
  500.     pop     ds
  501.   }
  502. }
  503.  
  504. //////////////////////////////////////////////////////////////
  505. // Initializes the random number generator with a new seed
  506. // based on the system time
  507. void randomize()
  508. {
  509.   srand((unsigned)time(NULL));
  510. }
  511.  
  512. //////////////////////////////////////////////////////////////
  513. // returns a value from 0 to x-1.
  514. // RAND_MX1 is RAND_MAX + 1 to insure that the boundary
  515. // value of x is never attained.
  516. int random(int x)
  517. {
  518.   return (int)((long)(rand()*(long)x)/(long)RAND_MX1);
  519. }
  520.  
  521. // DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
  522. // Function rad (theta : real) : real;
  523. // This calculates the degrees of an angle
  524. //   rad := theta * pi / 180
  525. float rad(float theta)
  526. {
  527.   return theta*PI/(float)180.0;
  528. }
  529.  
  530. int round(float x)
  531. {
  532.   if(x>=0)
  533.     return (int)(x+0.5);
  534.   else
  535.     return (int)(x-0.5);
  536. }
  537.  
  538. ////////////////  SetUpVirtual /////////////////////////
  539. // Sets up pointers to 2 virtual screens
  540.  
  541. void SetUpVirtual()
  542. {
  543.   VirtPtr=&Virtual[0];
  544.   Vaddr = FP_SEG(VirtPtr);
  545.   VirtPtr2=&Virtual2[0];
  546.   Vaddr2 = FP_SEG(VirtPtr2);
  547. }
  548.  
  549. //{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  550. //Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  551. //  { This draws a horizontal line from x1 to x2 on line y in color col }
  552. void Hline(int x1, int x2, int y, char col, int where)
  553. {
  554.  _asm
  555.  {
  556.   mov   ax,where
  557.   mov   es,ax
  558.   mov   ax,y
  559.   mov   di,ax
  560.   shl   ax,8
  561.   shl   di,6
  562.   add   di,ax
  563.   add   di,x1
  564.  
  565.   mov   al,col
  566.   mov   ah,al
  567.   mov   cx,x2
  568.   sub   cx,x1
  569.   shr   cx,1
  570.   jnc   lstart
  571.   stosb
  572. lstart :
  573.   rep   stosw
  574.  }
  575. }
  576.  
  577. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  578. // Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  579. // This puts a pixel on the screen by writing directly to memory. }
  580. // Assembly version
  581. void PutPixel2(int x, int y, char col, int where)
  582. {
  583.   _asm
  584.   {
  585.     mov     ax,where
  586.     mov     es,ax
  587.     mov     bx,x
  588.     mov     dx,y
  589.     mov     di,bx
  590.     mov     bx, dx   //               {; bx = dx}
  591.     shl     dx, 8
  592.     shl     bx, 6
  593.     add     dx, bx   //               {; dx = dx + bx (ie y*320)}
  594.     add     di, dx   //               {; finalise location}
  595.     mov     al, col
  596.     stosb
  597.   }
  598. }    
  599.  
  600. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  601. // Function Getpixel (X,Y : Integer; where:word):byte; assembler;
  602. // { This gets a pixel from the screen by reading directly from memory. }
  603. char GetPixel(int x, int y, int where)
  604. {
  605.   _asm
  606.   {
  607.   mov     ax,where
  608.   mov     es,ax
  609.   mov     bx,x
  610.   mov     dx,y
  611.   mov     di,bx
  612.   mov     bx, dx                  ; bx = dx}
  613.   shl     dx, 8
  614.   shl     bx, 6
  615.   add     dx, bx                  ; dx = dx + bx (ie y*320)}
  616.   add     di, dx                  ; finalise location}
  617.   mov     al, es:[di]
  618.   }
  619. }  
  620. // This generates warning of no return value, but
  621. // this is OK; value is returned in al. See pg. 279 "C For Yourself",
  622. // Microsoft Press.
  623.  
  624. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  625. // Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  626. //  { This loads the cel 'filename' into the pointer scrptr }
  627. void LoadCEL(char* FileName, char far* ScrPtr)
  628. {
  629.   FILE* fptr;
  630.   char far* TmpPtr;
  631.   
  632.   TmpPtr=ScrPtr;  // Do this so ScrPtr doesn't get incremented.
  633.   if((fptr=fopen(FileName,"rb"))==NULL)
  634.   {                                            
  635.     SetText();
  636.     printf("Error opening file %s\n",FileName);
  637.     exit(1);
  638.   }
  639.   fseek(fptr,(long)800,SEEK_SET);  //offset 800 from beginning of file.
  640.   fread(TmpPtr,sizeof(char),(unsigned)64000,fptr);
  641.   fclose(fptr);
  642. }  
  643.  
  644. void delay(int wait)
  645. {
  646.   long goal;
  647.   goal=(long)wait + clock();
  648.   while(goal>clock());
  649. }
  650.  
  651. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  652. // Procedure InitChain4; ASSEMBLER;
  653. //   {  This procedure gets you into Chain 4 mode }
  654. //   Also see listing 10.1, pg. 206 of Power Graphics Programming, Abrash
  655. void InitChain4(int ScrSize)
  656. {
  657.  _asm 
  658.  {
  659.     mov    ax, 13h
  660.     int    10h       ;  { Get into MCGA Mode }
  661.  
  662.     mov    dx, 3c4h  ;  { Port 3c4h = Sequencer Address Register }
  663.     mov    al, 4     ;  { Index 4 = memory mode }
  664.     out    dx, al
  665.     inc    dx        ;  { Port 3c5h ... here we set the mem mode }
  666.     in     al, dx
  667.     and    al, not 08h ; turn off bit 3, the C4 bit, see pg 357 Ferraro.
  668.     or     al, 04h     ; turn on bit 2, the O/E bit
  669.     out    dx, al
  670.     mov    dx, 3ceh  ; Port 3ceh = Graphics Address Register
  671.     mov    al, 5     ; Index 5 = Mode
  672.     out    dx, al
  673.     inc    dx
  674.     in     al, dx
  675.     and    al, not 10h ; turn off bit 4, the O/E bit
  676.     out    dx, al
  677.     dec    dx
  678.     mov    al, 6     ; Index 6 = Miscellaneous Register
  679.     out    dx, al
  680.     inc    dx
  681.     in     al, dx
  682.     and    al, not 02h  ; Turn of bit 1, chain odd/even
  683.     out    dx, al
  684.     mov    dx, 3c4h  ; Sequencer Address Register
  685.     mov    ax, (0fh shl 8) + 2 ; write 0fh to register: enable all 4 planes
  686.     out    dx, ax
  687.     mov    ax, 0a000h
  688.     mov    es, ax
  689.     sub    di, di
  690.     mov    ax, 0000h ;  Store 0000h to es:di, 32K times:
  691.     mov    cx, 32768 ;  8000h=32K words = 64K bytes
  692.     cld
  693.     rep    stosw      ;     { Clear garbage off the screen ... }
  694.  
  695.     mov    dx, 3d4h
  696.     mov    al, 14h  ; underline register
  697.     out    dx, al
  698.     inc    dx
  699.     in     al, dx
  700.     and    al, not 40h ; Turn off double word addressing, see pg 380 Ferraro
  701.     out    dx, al
  702.     dec    dx
  703.     mov    al, 17h  ; mode control register
  704.     out    dx, al
  705.     inc    dx
  706.     in     al, dx
  707.     or     al, 40h  ; byte mode
  708.     out    dx, al
  709.  
  710.     mov    dx, 3d4h
  711.     mov    al, 13h    ;   Offset register, = logical display width
  712.     out    dx, al
  713.     inc    dx
  714.     mov    ax, ScrSize   ;    Size * 8 = Pixels across. Only 320 are visible
  715.     out    dx, al        ;    Note that size is a keyword in MASM!
  716.   }
  717. }
  718.  
  719.  
  720. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  721. // Procedure C4PutPixel(X,Y : Word; Col : Byte); ASSEMBLER;
  722. //   { This puts a pixel on the chain 4 screen }
  723. void C4PutPixel(int x, int y, char col, int ScrSize)
  724. {
  725.   _asm 
  726.   {
  727.     mov    ax,y
  728.     xor    bx,bx
  729.     mov    bx,ScrSize
  730.     imul   bx
  731.     shl    ax,1
  732.     mov    bx,ax
  733.     mov    ax, x
  734.     mov    cx, ax
  735.     shr    ax, 2
  736.     add    bx, ax
  737.     and    cx, 00000011b
  738.     mov    ah, 1
  739.     shl    ah, cl
  740.     mov    dx, 3c4h        ;         { Sequencer Register    }
  741.     mov    al, 2           ;         { Map Mask Index        }
  742.     out    dx, ax
  743.  
  744.     mov    ax, 0a000h
  745.     mov    es, ax
  746.     mov    al, col
  747.     mov    es: [bx], al
  748.   }
  749. }
  750.  
  751. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  752. // Procedure Plane(Which : Byte); ASSEMBLER;
  753. //   { This sets the plane to write to in Chain 4}
  754. void Plane(char Which)
  755. {
  756.  _asm
  757.  {
  758.    mov     al, 2h
  759.    mov     ah, 1
  760.    mov     cl, Which
  761.    shl     ah, cl
  762.    mov     dx, 3c4h     ;            { Sequencer Register    }
  763.    out     dx, ax
  764.  }
  765. }
  766.  
  767.  
  768. // {DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
  769. // procedure moveto(x, y : word);
  770. //   { This moves to position x*4,y on a chain 4 screen }
  771. void moveto(int x, int y, int Size)
  772. {
  773.   int o;
  774.   o=y*Size*2+x;
  775.   _asm
  776.   {
  777.     mov    bx, o
  778.     mov    ah, bh
  779.     mov    al, 0ch
  780.  
  781.     mov    dx, 3d4h
  782.     out    dx, ax
  783.  
  784.     mov    ah, bl
  785.     mov    al, 0dh
  786.     mov    dx, 3d4h
  787.     out    dx, ax
  788.   }
  789. }
  790.  
  791.